#pragma once

#include <iostream>
#include "Connection.hpp"
#include "Reactor.hpp"
using namespace log_ns;

const static int buffersize = 512;

class HandlerConnection
{

public:
    HandlerConnection(handler_t process) : _process(process)
    {
    }
    void HandlerRecver(Connection *conn)
    {
        // 重置错误码
        errno = 0;
        // 1.直接读取
        // LOG(DEBUG, "client 给我发了消息: %d\n", conn->Sockfd());
        while (true)
        {
            char buffer[buffersize];
            int n = ::recv(conn->Sockfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0) // 说明获取成功
            {
                buffer[n] = 0; // 数据块
                // 将每一次从同一个fd中读取到的buffer拼接起来，临时放在inbuffer里
                conn->AppendInbuffer(buffer);
            }
            else // 出错
            {
                // 本轮数据读取完毕
                if (errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 最后统一进行异常处理
                    conn->_handler_excepter(conn);
                    return;
                }
            }
        }
        // 2.业务处理
        //  一定读取完毕，处理数据
        std::cout << "Inbuffer content: " << conn->Inbuffer() << std::endl;
        // 由上层来进行报文分析
        _process(conn);
    }
    void HandlerSender(Connection *conn)
    {
        // 重置错误码
        errno = 0;
        // 1.直接写
        while (true)
        {
            ssize_t n = ::send(conn->Sockfd(), conn->Outbuffer().c_str(), conn->Outbuffer().size(), 0);
            if (n > 0)
            {
                // 将有效内容发送成功，清理发送缓冲区已发送的数据大小
                conn->DiscardOutbuffer(n);
                // 数据发送完毕
                if (conn->Outbuffer().empty())
                    break; // 修改为break
            }
            else if (n == 0)
            {
                // 在我们今天的代码不存在，outbuffer为空，写事件没必要处理
                return;
            }
            else
            {
                // <0不一定是出错了， 有可能是发送缓冲区写满了
                if (errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 发送失败，不能继续发送，进入异常处理逻辑
                    conn->_handler_excepter(conn);
                }
            }
            // 2.代码运行到这里，只能是发送条件不满足，outbuffer已经被写满；但是有可能数据没发送完，因此要开启EPOLLOUT
            if (!conn->Outbuffer().empty()) // 缓冲区还有数据
            {
                // 开启关心写事件, 因此需要在Reactor中添加修改文件描述符的事件的关心
                conn->_R->EnableConnectionReadWrite(conn->Sockfd(), true, true);
                // 开启写事件关心后，数据未写完，就会自动继续写，直到写完，写完数据后，
                // 关闭写事件，这里的处理，就转到判断发送缓冲区是否为空来处理了
            }
            else
            {
                // 是否还需要关系剩余数据
                conn->_R->EnableConnectionReadWrite(conn->Sockfd(), true, false);
            }
        }
    }
    void HandlerExcepter(Connection *conn)
    {
        // 整个代码的所有的异常处理，全在这里处理读写错误，客户端关闭连接
        // 删除连接
        conn->_R->DelConnection(conn->Sockfd());
    }

private:
    handler_t _process;
};
